package com.bangyo.common.filter;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.sothis.util.StringUtils;
import org.sothis.util.crypto.CipherProcessor;

import com.bangyo.user.ApplicationUser;
import com.bangyo.user.searcher.ApplicationUserSearcherByLoginName;

public class UserLoginByCookieFilter extends AbstractHttpFilter
{
    protected void doHttpFilter(HttpServletRequest request,
        HttpServletResponse response, FilterChain chain) throws IOException,
        ServletException
    {
        Object att = request.getSession().getAttribute("userPoin");
        if (null!=att)
        {
            try
            {
                long userPoin = Long.parseLong(att.toString());
                if (userPoin>0)
                {
                    if (logger.isDebugEnabled())
                    {
                        logger.debug("User with poin["+userPoin
                            +"] already loggedin.");
                    }
                    chain.doFilter(request, response);
                    return;
                }
            }
            catch (NumberFormatException e)
            {
            }
        }
        if (logger.isDebugEnabled())
        {
            logger.debug("User not login, try to find cookie information.");
        }
        loginByCookie(request);

        chain.doFilter(request, response);
    }

    private boolean loginByCookie(HttpServletRequest request)
    {
        Cookie[] cookies = request.getCookies();
        if (null==cookies)
        {
            return false;
        }
        for (int i = 0; i<cookies.length; i++)
        {
            if (cookies[i].getName().equals(loginCookieName))
            {
                if (StringUtils.isNullOrEmpty(cookies[i].getValue()))
                {
                    if (logger.isDebugEnabled())
                    {
                        logger.debug("cookie invalid.");
                    }
                    return false;
                }
                if (logger.isDebugEnabled())
                {
                    logger.debug("cookie value=["+cookies[i].getValue()+"]");
                }
                byte[] key;
                try
                {
                    key = StringUtils.hexToByte(URLDecoder.decode(cookies[i]
                        .getValue(), "UTF-8"));
                }
                catch (UnsupportedEncodingException e)
                {
                    if (logger.isWarnEnabled())
                    {
                        logger.warn("cookie decode falied: ", e);
                    }
                    e.printStackTrace();
                    return false;
                }
                if (key.length%8!=0)
                {
                    if (logger.isDebugEnabled())
                    {
                        logger.debug("cookie["+cookies[i].getValue()
                            +"] is not a valid key.");
                    }
                    return false;
                }
                String loginName = new String(cipherProcessor.decrypt(key));
                if (logger.isDebugEnabled())
                {
                    logger.debug("find cookie information of user["+loginName
                        +"].");
                }
                applicationUserSearcherByLoginName.setLoginName(loginName);
                ApplicationUser user = applicationUserSearcherByLoginName
                    .getSingleEntity();
                if (null!=user)
                {
                    request.getSession().setAttribute("userPoin",
                        new Long(user.getPoin()));
                    request.getSession().setAttribute("userNickName",
                        user.getNickName());
                    if (logger.isDebugEnabled())
                    {
                        logger.debug("User["+loginName+"] login success.");
                    }
                    return true;
                }
                if (logger.isDebugEnabled())
                {
                    logger.debug("User["+loginName+"] not found.");
                }
                return false;
            }
        }
        if (logger.isDebugEnabled())
        {
            logger.debug("No cookie named["+loginCookieName+"] found.");
        }
        return false;
    }

    private String loginCookieName = null;

    private CipherProcessor cipherProcessor = null;

    private ApplicationUserSearcherByLoginName applicationUserSearcherByLoginName = null;

    public void setApplicationUserSearcherByLoginName(
        ApplicationUserSearcherByLoginName applicationUserSearcherByLoginName)
    {
        this.applicationUserSearcherByLoginName = applicationUserSearcherByLoginName;
    }

    public void setCipherProcessor(CipherProcessor cipherProcessor)
    {
        this.cipherProcessor = cipherProcessor;
    }

    public void setLoginCookieName(String loginCookieName)
    {
        this.loginCookieName = loginCookieName;
    }
}
